home *** CD-ROM | disk | FTP | other *** search
/ Personal Computer World 2008 February / PCWFEB08.iso / Software / Resources / Developers / XAMPP 1.5.4 / Windows installer / xampp-win32-1.5.4-installer.exe / xampp / php / pear / PEAR / DependencyDB.php < prev    next >
Encoding:
PHP Script  |  2005-12-02  |  23.1 KB  |  655 lines

  1. <?php
  2. /**
  3.  * PEAR_DependencyDB, advanced installed packages dependency database
  4.  *
  5.  * PHP versions 4 and 5
  6.  *
  7.  * LICENSE: This source file is subject to version 3.0 of the PHP license
  8.  * that is available through the world-wide-web at the following URI:
  9.  * http://www.php.net/license/3_0.txt.  If you did not receive a copy of
  10.  * the PHP License and are unable to obtain it through the web, please
  11.  * send a note to license@php.net so we can mail you a copy immediately.
  12.  *
  13.  * @category   pear
  14.  * @package    PEAR
  15.  * @author     Tomas V. V. Cox <cox@idecnet.com>
  16.  * @author     Greg Beaver <cellog@php.net>
  17.  * @copyright  1997-2005 The PHP Group
  18.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  19.  * @version    CVS: $Id: DependencyDB.php,v 1.29 2005/09/15 20:10:11 cellog Exp $
  20.  * @link       http://pear.php.net/package/PEAR
  21.  * @since      File available since Release 1.4.0a1
  22.  */
  23.  
  24. /**
  25.  * Needed for error handling
  26.  */
  27. require_once 'PEAR.php';
  28. require_once 'PEAR/Config.php';
  29.  
  30. /**
  31.  * Track dependency relationships between installed packages
  32.  * @category   pear
  33.  * @package    PEAR
  34.  * @author     Greg Beaver <cellog@php.net>
  35.  * @author     Tomas V.V.Cox <cox@idec.net.com>
  36.  * @copyright  1997-2005 The PHP Group
  37.  * @license    http://www.php.net/license/3_0.txt  PHP License 3.0
  38.  * @version    Release: 1.4.5
  39.  * @link       http://pear.php.net/package/PEAR
  40.  * @since      Class available since Release 1.4.0a1
  41.  */
  42. class PEAR_DependencyDB
  43. {
  44.     // {{{ properties
  45.  
  46.     /**
  47.      * This is initialized by {@link setConfig()}
  48.      * @var PEAR_Config
  49.      * @access private
  50.      */
  51.     var $_config;
  52.     /**
  53.      * This is initialized by {@link setConfig()}
  54.      * @var PEAR_Registry
  55.      * @access private
  56.      */
  57.     var $_registry;
  58.     /**
  59.      * Filename of the dependency DB (usually .depdb)
  60.      * @var string
  61.      * @access private
  62.      */
  63.     var $_depdb = false;
  64.     /**
  65.      * File name of the lockfile (usually .depdblock)
  66.      * @var string
  67.      * @access private
  68.      */
  69.     var $_lockfile = false;
  70.     /**
  71.      * Open file resource for locking the lockfile
  72.      * @var resource|false
  73.      * @access private
  74.      */
  75.     var $_lockFp = false;
  76.     /**
  77.      * API version of this class, used to validate a file on-disk
  78.      * @var string
  79.      * @access private
  80.      */
  81.     var $_version = '1.0';
  82.     /**
  83.      * Cached dependency database file
  84.      * @var array|null
  85.      * @access private
  86.      */
  87.     var $_cache;
  88.  
  89.     // }}}
  90.     // {{{ & singleton()
  91.  
  92.     /**
  93.      * Get a raw dependency database.  Calls setConfig() and assertDepsDB()
  94.      * @param PEAR_Config
  95.      * @param string|false full path to the dependency database, or false to use default
  96.      * @return PEAR_DependencyDB|PEAR_Error
  97.      * @static
  98.      */
  99.     function &singleton(&$config, $depdb = false)
  100.     {
  101.         if (!isset($GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  102.               [$config->get('php_dir', null, 'pear.php.net')])) {
  103.             $a = new PEAR_DependencyDB;
  104.             $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  105.               [$config->get('php_dir', null, 'pear.php.net')] = &$a;
  106.             $a->setConfig($config, $depdb);
  107.             if (PEAR::isError($e = $a->assertDepsDB())) {
  108.                 return $e;
  109.             }
  110.         }
  111.         return $GLOBALS['_PEAR_DEPENDENCYDB_INSTANCE']
  112.               [$config->get('php_dir', null, 'pear.php.net')];
  113.     }
  114.  
  115.     /**
  116.      * Set up the registry/location of dependency DB
  117.      * @param PEAR_Config|false
  118.      * @param string|false full path to the dependency database, or false to use default
  119.      */
  120.     function setConfig(&$config, $depdb = false)
  121.     {
  122.         if (!$config) {
  123.             $this->_config = &PEAR_Config::singleton();
  124.         } else {
  125.             $this->_config = &$config;
  126.         }
  127.         $this->_registry = &$this->_config->getRegistry();
  128.         if (!$depdb) {
  129.             $this->_depdb = $this->_config->get('php_dir', null, 'pear.php.net') .
  130.                 DIRECTORY_SEPARATOR . '.depdb';
  131.         } else {
  132.             $this->_depdb = $depdb;
  133.         }
  134.         $this->_lockfile = dirname($this->_depdb) . DIRECTORY_SEPARATOR . '.depdblock';
  135.     }
  136.     // }}}
  137.  
  138.     function hasWriteAccess()
  139.     {
  140.         if (!@file_exists($this->_depdb)) {
  141.             $dir = $this->_depdb;
  142.             while ($dir && $dir != '.') {
  143.                 $dir = dirname($dir); // cd ..
  144.                 if ($dir != '.' && @file_exists($dir)) {
  145.                     if (@is_writeable($dir)) {
  146.                         return true;
  147.                     } else {
  148.                         return false;
  149.                     }
  150.                 }
  151.             }
  152.             return false;
  153.         }
  154.         return @is_writeable($this->_depdb);
  155.     }
  156.  
  157.     // {{{ assertDepsDB()
  158.  
  159.     /**
  160.      * Create the dependency database, if it doesn't exist.  Error if the database is
  161.      * newer than the code reading it.
  162.      * @return void|PEAR_Error
  163.      */
  164.     function assertDepsDB()
  165.     {
  166.         if (!is_file($this->_depdb)) {
  167.             $this->rebuildDB();
  168.         } else {
  169.             $depdb = $this->_getDepDB();
  170.             // Datatype format has been changed, rebuild the Deps DB
  171.             if ($depdb['_version'] < $this->_version) {
  172.                 $this->rebuildDB();
  173.             }
  174.             if ($depdb['_version']{0} > $this->_version{0}) {
  175.                 return PEAR::raiseError('Dependency database is version ' .
  176.                     $depdb['_version'] . ', and we are version ' .
  177.                     $this->_version . ', cannot continue');
  178.             }
  179.         }
  180.     }
  181.  
  182.     /**
  183.      * Get a list of installed packages that depend on this package
  184.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  185.      * @return array|false
  186.      */
  187.     function getDependentPackages(&$pkg)
  188.     {
  189.         $data = $this->_getDepDB();
  190.         if (is_object($pkg)) {
  191.             $channel = strtolower($pkg->getChannel());
  192.             $package = strtolower($pkg->getPackage());
  193.         } else {
  194.             $channel = strtolower($pkg['channel']);
  195.             $package = strtolower($pkg['package']);
  196.         }
  197.         if (isset($data['packages'][$channel][$package])) {
  198.             return $data['packages'][$channel][$package];
  199.         }
  200.         return false;
  201.     }
  202.  
  203.     /**
  204.      * Get a list of the actual dependencies of installed packages that depend on
  205.      * a package.
  206.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  207.      * @return array|false
  208.      */
  209.     function getDependentPackageDependencies(&$pkg)
  210.     {
  211.         $data = $this->_getDepDB();
  212.         if (is_object($pkg)) {
  213.             $channel = strtolower($pkg->getChannel());
  214.             $package = strtolower($pkg->getPackage());
  215.         } else {
  216.             $channel = strtolower($pkg['channel']);
  217.             $package = strtolower($pkg['package']);
  218.         }
  219.         $depend = $this->getDependentPackages($pkg);
  220.         if (!$depend) {
  221.             return false;
  222.         }
  223.         $dependencies = array();
  224.         foreach ($depend as $info) {
  225.             $temp = $this->getDependencies($info);
  226.             foreach ($temp as $dep) {
  227.                 if (strtolower($dep['dep']['channel']) == strtolower($channel) &&
  228.                       strtolower($dep['dep']['name']) == strtolower($package)) {
  229.                     $dependencies[$info['channel']][$info['package']][] = $dep;
  230.                 }
  231.             }
  232.         }
  233.         return $dependencies;
  234.     }
  235.  
  236.     /**
  237.      * Get a list of dependencies of this installed package
  238.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array
  239.      * @return array|false
  240.      */
  241.     function getDependencies(&$pkg)
  242.     {
  243.         if (is_object($pkg)) {
  244.             $channel = strtolower($pkg->getChannel());
  245.             $package = strtolower($pkg->getPackage());
  246.         } else {
  247.             $channel = strtolower($pkg['channel']);
  248.             $package = strtolower($pkg['package']);
  249.         }
  250.         $data = $this->_getDepDB();
  251.         if (isset($data['dependencies'][$channel][$package])) {
  252.             return $data['dependencies'][$channel][$package];
  253.         }
  254.         return false;
  255.     }
  256.  
  257.     /**
  258.      * Determine whether $parent depends on $child, near or deep
  259.      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
  260.      * @param array|PEAR_PackageFile_v2|PEAR_PackageFile_v2
  261.      */
  262.     function dependsOn($parent, $child)
  263.     {
  264.         $c = array();
  265.         $this->_getDepDB();
  266.         return $this->_dependsOn($parent, $child, $c);
  267.     }
  268.     
  269.     function _dependsOn($parent, $child, &$checked)
  270.     {
  271.         if (is_object($parent)) {
  272.             $channel = strtolower($parent->getChannel());
  273.             $package = strtolower($parent->getPackage());
  274.         } else {
  275.             $channel = strtolower($parent['channel']);
  276.             $package = strtolower($parent['package']);
  277.         }
  278.         if (is_object($child)) {
  279.             $depchannel = strtolower($child->getChannel());
  280.             $deppackage = strtolower($child->getPackage());
  281.         } else {
  282.             $depchannel = strtolower($child['channel']);
  283.             $deppackage = strtolower($child['package']);
  284.         }
  285.         if (isset($checked[$channel][$package][$depchannel][$deppackage])) {
  286.             return false; // avoid endless recursion
  287.         }
  288.         $checked[$channel][$package][$depchannel][$deppackage] = true;
  289.         if (!isset($this->_cache['dependencies'][$channel][$package])) {
  290.             return false;
  291.         }
  292.         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
  293.             if (strtolower($info['dep']['channel']) == strtolower($depchannel) &&
  294.                   strtolower($info['dep']['name']) == strtolower($deppackage)) {
  295.                 return true;
  296.             }
  297.         }
  298.         foreach ($this->_cache['dependencies'][$channel][$package] as $info) {
  299.             if ($this->_dependsOn(array(
  300.                     'channel' => $info['dep']['channel'],
  301.                     'package' => $info['dep']['name']), $child, $checked)) {
  302.                 return true;
  303.             }
  304.         }
  305.         return false;
  306.     }
  307.  
  308.     /**
  309.      * Register dependencies of a package that is being installed or upgraded
  310.      * @param PEAR_PackageFile_v2|PEAR_PackageFile_v2
  311.      */
  312.     function installPackage(&$package)
  313.     {
  314.         $data = $this->_getDepDB();
  315.         unset($this->_cache);
  316.         $this->_setPackageDeps($data, $package);
  317.         $this->_writeDepDB($data);
  318.     }
  319.  
  320.     /**
  321.      * Remove dependencies of a package that is being uninstalled, or upgraded.
  322.      *
  323.      * Upgraded packages first uninstall, then install
  324.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2|array If an array, then it must have
  325.      *        indices 'channel' and 'package'
  326.      */
  327.     function uninstallPackage(&$pkg)
  328.     {
  329.         $data = $this->_getDepDB();
  330.         unset($this->_cache);
  331.         if (is_object($pkg)) {
  332.             $channel = strtolower($pkg->getChannel());
  333.             $package = strtolower($pkg->getPackage());
  334.         } else {
  335.             $channel = strtolower($pkg['channel']);
  336.             $package = strtolower($pkg['package']);
  337.         }
  338.         if (!isset($data['dependencies'][$channel][$package])) {
  339.             return true;
  340.         }
  341.         foreach ($data['dependencies'][$channel][$package] as $dep) {
  342.             $found = false;
  343.             if (isset($dep['dep']['uri'])) {
  344.                 $depchannel = '__uri';
  345.             } else {
  346.                 $depchannel = strtolower($dep['dep']['channel']);
  347.             }
  348.             if (isset($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
  349.                 foreach ($data['packages'][$depchannel][strtolower($dep['dep']['name'])] as
  350.                       $i => $info) {
  351.                     if ($info['channel'] == $channel &&
  352.                           $info['package'] == $package) {
  353.                         $found = true;
  354.                         break;
  355.                     }
  356.                 }
  357.             }
  358.             if ($found) {
  359.                 unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])][$i]);
  360.                 if (!count($data['packages'][$depchannel][strtolower($dep['dep']['name'])])) {
  361.                     unset($data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
  362.                     if (!count($data['packages'][$depchannel])) {
  363.                         unset($data['packages'][$depchannel]);
  364.                     }
  365.                 } else {
  366.                     $data['packages'][$depchannel][strtolower($dep['dep']['name'])] =
  367.                         array_values(
  368.                             $data['packages'][$depchannel][strtolower($dep['dep']['name'])]);
  369.                 }
  370.             }
  371.         }
  372.         unset($data['dependencies'][$channel][$package]);
  373.         if (!count($data['dependencies'][$channel])) {
  374.             unset($data['dependencies'][$channel]);
  375.         }
  376.         if (!count($data['dependencies'])) {
  377.             unset($data['dependencies']);
  378.         }
  379.         if (!count($data['packages'])) {
  380.             unset($data['packages']);
  381.         }
  382.         $this->_writeDepDB($data);
  383.     }
  384.  
  385.     /**
  386.      * Rebuild the dependency DB by reading registry entries.
  387.      * @return true|PEAR_Error
  388.      */
  389.     function rebuildDB()
  390.     {
  391.         $depdb = array('_version' => $this->_version);
  392.         if (!$this->hasWriteAccess()) {
  393.             // allow startup for read-only with older Registry
  394.             return $depdb;
  395.         }
  396.         $packages = $this->_registry->listAllPackages();
  397.         foreach ($packages as $channel => $ps) {
  398.             foreach ($ps as $package) {
  399.                 $package = $this->_registry->getPackage($package, $channel);
  400.                 $this->_setPackageDeps($depdb, $package);
  401.             }
  402.         }
  403.         $error = $this->_writeDepDB($depdb);
  404.         if (PEAR::isError($error)) {
  405.             return $error;
  406.         }
  407.         $this->_cache = $depdb;
  408.         return true;
  409.     }
  410.  
  411.     /**
  412.      * Register usage of the dependency DB to prevent race conditions
  413.      * @param int one of the LOCK_* constants
  414.      * @return true|PEAR_Error
  415.      * @access private
  416.      */
  417.     function _lock($mode = LOCK_EX)
  418.     {
  419.         if (!eregi('Windows 9', php_uname())) {
  420.             if ($mode != LOCK_UN && is_resource($this->_lockFp)) {
  421.                 // XXX does not check type of lock (LOCK_SH/LOCK_EX)
  422.                 return true;
  423.             }
  424.             $open_mode = 'w';
  425.             // XXX People reported problems with LOCK_SH and 'w'
  426.             if ($mode === LOCK_SH) {
  427.                 if (@!is_file($this->_lockfile)) {
  428.                     touch($this->_lockfile);
  429.                 }
  430.                 $open_mode = 'r';
  431.             }
  432.  
  433.             if (!is_resource($this->_lockFp)) {
  434.                 $this->_lockFp = @fopen($this->_lockfile, $open_mode);
  435.             }
  436.             if (!is_resource($this->_lockFp)) {
  437.                 return PEAR::raiseError("could not create Dependency lock file" .
  438.                                          (isset($php_errormsg) ? ": " . $php_errormsg : ""));
  439.             }
  440.             if (!(int)flock($this->_lockFp, $mode)) {
  441.                 switch ($mode) {
  442.                     case LOCK_SH: $str = 'shared';    break;
  443.                     case LOCK_EX: $str = 'exclusive'; break;
  444.                     case LOCK_UN: $str = 'unlock';    break;
  445.                     default:      $str = 'unknown';   break;
  446.                 }
  447.                 return PEAR::raiseError("could not acquire $str lock ($this->_lockfile)");
  448.             }
  449.         }
  450.         return true;
  451.     }
  452.  
  453.     /**
  454.      * Release usage of dependency DB
  455.      * @return true|PEAR_Error
  456.      * @access private
  457.      */
  458.     function _unlock()
  459.     {
  460.         $ret = $this->_lock(LOCK_UN);
  461.         if (is_resource($this->_lockFp)) {
  462.             fclose($this->_lockFp);
  463.         }
  464.         $this->_lockFp = null;
  465.         return $ret;
  466.     }
  467.  
  468.     /**
  469.      * Load the dependency database from disk, or return the cache
  470.      * @return array|PEAR_Error
  471.      */
  472.     function _getDepDB()
  473.     {
  474.         if (!$this->hasWriteAccess()) {
  475.             return array('_version' => $this->_version);
  476.         }
  477.         if (isset($this->_cache)) {
  478.             return $this->_cache;
  479.         }
  480.         if (!$fp = fopen($this->_depdb, 'r')) {
  481.             $err = PEAR::raiseError("Could not open dependencies file `".$this->_depdb."'");
  482.             return $err;
  483.         }
  484.         $rt = get_magic_quotes_runtime();
  485.         set_magic_quotes_runtime(0);
  486.         clearstatcache();
  487.         if (function_exists('file_get_contents')) {
  488.             fclose($fp);
  489.             $data = unserialize(file_get_contents($this->_depdb));
  490.         } else {
  491.             $data = unserialize(fread($fp, filesize($this->_depdb)));
  492.             fclose($fp);
  493.         }
  494.         set_magic_quotes_runtime($rt);
  495.         $this->_cache = $data;
  496.         return $data;
  497.     }
  498.  
  499.     /**
  500.      * Write out the dependency database to disk
  501.      * @param array the database
  502.      * @return true|PEAR_Error
  503.      * @access private
  504.      */
  505.     function _writeDepDB(&$deps)
  506.     {
  507.         if (PEAR::isError($e = $this->_lock(LOCK_EX))) {
  508.             return $e;
  509.         }
  510.         if (!$fp = fopen($this->_depdb, 'wb')) {
  511.             $this->_unlock();
  512.             return PEAR::raiseError("Could not open dependencies file `".$this->_depdb."' for writing");
  513.         }
  514.         $rt = get_magic_quotes_runtime();
  515.         set_magic_quotes_runtime(0);
  516.         fwrite($fp, serialize($deps));
  517.         set_magic_quotes_runtime($rt);
  518.         fclose($fp);
  519.         $this->_unlock();
  520.         $this->_cache = $deps;
  521.         return true;
  522.     }
  523.  
  524.     /**
  525.      * Register all dependencies from a package in the dependencies database, in essence
  526.      * "installing" the package's dependency information
  527.      * @param array the database
  528.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  529.      * @access private
  530.      */
  531.     function _setPackageDeps(&$data, &$pkg)
  532.     {
  533.         $pkg->setConfig($this->_config);
  534.         if ($pkg->getPackagexmlVersion() == '1.0') {
  535.             $gen = &$pkg->getDefaultGenerator();
  536.             $deps = $gen->dependenciesToV2();
  537.         } else {
  538.             $deps = $pkg->getDeps(true);
  539.         }
  540.         if (!$deps) {
  541.             return;
  542.         }
  543.         $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())]
  544.             = array();
  545.         if (isset($deps['required']['package'])) {
  546.             if (!isset($deps['required']['package'][0])) {
  547.                 $deps['required']['package'] = array($deps['required']['package']);
  548.             }
  549.             foreach ($deps['required']['package'] as $dep) {
  550.                 $this->_registerDep($data, $pkg, $dep, 'required');
  551.             }
  552.         }
  553.         if (isset($deps['optional']['package'])) {
  554.             if (!isset($deps['optional']['package'][0])) {
  555.                 $deps['optional']['package'] = array($deps['optional']['package']);
  556.             }
  557.             foreach ($deps['optional']['package'] as $dep) {
  558.                 $this->_registerDep($data, $pkg, $dep, 'optional');
  559.             }
  560.         }
  561.         if (isset($deps['required']['subpackage'])) {
  562.             if (!isset($deps['required']['subpackage'][0])) {
  563.                 $deps['required']['subpackage'] = array($deps['required']['subpackage']);
  564.             }
  565.             foreach ($deps['required']['subpackage'] as $dep) {
  566.                 $this->_registerDep($data, $pkg, $dep, 'required');
  567.             }
  568.         }
  569.         if (isset($deps['optional']['subpackage'])) {
  570.             if (!isset($deps['optional']['subpackage'][0])) {
  571.                 $deps['optional']['subpackage'] = array($deps['optional']['subpackage']);
  572.             }
  573.             foreach ($deps['optional']['subpackage'] as $dep) {
  574.                 $this->_registerDep($data, $pkg, $dep, 'optional');
  575.             }
  576.         }
  577.         if (isset($deps['group'])) {
  578.             if (!isset($deps['group'][0])) {
  579.                 $deps['group'] = array($deps['group']);
  580.             }
  581.             foreach ($deps['group'] as $group) {
  582.                 if (isset($group['package'])) {
  583.                     if (!isset($group['package'][0])) {
  584.                         $group['package'] = array($group['package']);
  585.                     }
  586.                     foreach ($group['package'] as $dep) {
  587.                         $this->_registerDep($data, $pkg, $dep, 'optional',
  588.                             $group['attribs']['name']);
  589.                     }
  590.                 }
  591.                 if (isset($group['subpackage'])) {
  592.                     if (!isset($group['subpackage'][0])) {
  593.                         $group['subpackage'] = array($group['subpackage']);
  594.                     }
  595.                     foreach ($group['subpackage'] as $dep) {
  596.                         $this->_registerDep($data, $pkg, $dep, 'optional',
  597.                             $group['attribs']['name']);
  598.                     }
  599.                 }
  600.             }
  601.         }
  602.         if ($data['dependencies'][strtolower($pkg->getChannel())]
  603.               [strtolower($pkg->getPackage())] == array()) {
  604.             unset($data['dependencies'][strtolower($pkg->getChannel())]
  605.               [strtolower($pkg->getPackage())]);
  606.             if (!count($data['dependencies'][strtolower($pkg->getChannel())])) {
  607.                 unset($data['dependencies'][strtolower($pkg->getChannel())]);
  608.             }
  609.         }
  610.     }
  611.  
  612.     /**
  613.      * @param array the database
  614.      * @param PEAR_PackageFile_v1|PEAR_PackageFile_v2
  615.      * @param array the specific dependency
  616.      * @param required|optional whether this is a required or an optional dep
  617.      * @param string|false dependency group this dependency is from, or false for ordinary dep
  618.      */
  619.     function _registerDep(&$data, &$pkg, $dep, $type, $group = false)
  620.     {
  621.         $info = array(
  622.             'dep' => $dep,
  623.             'type' => $type,
  624.             'group' => $group);
  625.  
  626.         if (isset($dep['channel'])) {
  627.             $depchannel = $dep['channel'];
  628.         } else {
  629.             $depchannel = '__uri';
  630.         }
  631.         $data['dependencies'][strtolower($pkg->getChannel())][strtolower($pkg->getPackage())][]
  632.             = $info;
  633.         if (isset($data['packages'][strtolower($depchannel)][strtolower($dep['name'])])) {
  634.             $found = false;
  635.             foreach ($data['packages'][strtolower($depchannel)][strtolower($dep['name'])]
  636.                   as $i => $p) {
  637.                 if ($p['channel'] == strtolower($pkg->getChannel()) &&
  638.                       $p['package'] == strtolower($pkg->getPackage())) {
  639.                     $found = true;
  640.                     break;
  641.                 }
  642.             }
  643.             if (!$found) {
  644.                 $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
  645.                     = array('channel' => strtolower($pkg->getChannel()),
  646.                             'package' => strtolower($pkg->getPackage()));
  647.             }
  648.         } else {
  649.             $data['packages'][strtolower($depchannel)][strtolower($dep['name'])][]
  650.                 = array('channel' => strtolower($pkg->getChannel()),
  651.                         'package' => strtolower($pkg->getPackage()));
  652.         }
  653.     }
  654. }
  655. ?>